package com.gitee.lougnib.simple.orika.util;

import java.util.List;

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeFactory;

/**
 * Orika 相关的工具类。
 *
 * @author lougnib@163.com
 * @since 2021/08/05
 * @version 2021/08/06
 */
public class OrikaUtil {

	/** Orika 映射实例。 */
	private static MapperFacade mapper;

	static {
		MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
		mapper = mapperFactory.getMapperFacade();
	}

	/**
	 * 获取并缓存 Type 类型。转换列表数据时，性能更加。
	 *
	 * @param clazz 类
	 */
	public static <T> Type<T> getType(final Class<T> clazz) {
		return TypeFactory.valueOf(clazz);
	}

	/**
	 * 映射出一个新类型的数据对象。
	 *
	 * @param data 源数据
	 * @param destinationClass 目标类
	 * @return 目标类型的数据对象
	 */
	public static <T, D> D map(final T data, final Class<D> destinationClass) {
		return mapper.map(data, destinationClass);
	}

	/**
	 * 映射出一个新类型的对象。预先通过 getType() 方法获取并缓存 Type 类型，性能更加。
	 *
	 * @param data 源数据
	 * @param sourceType 源类型
	 * @param destinationType 目标类型
	 * @return 目标类型的数据对象
	 */
	public static <T, D> D map(final T data, final Type<T> sourceType, final Type<D> destinationType) {
		return mapper.map(data, sourceType, destinationType);
	}

	/**
	 * 映射出一个新类型的数据对象列表。
	 *
	 * @param dataList 源数据列表
	 * @param sourceType 源类型
	 * @param destinationType 目标类型
	 * @return 目标类型的数据对象列表
	 */
	public static <T, D> List<D> mapAsList(Iterable<T> dataList, final Class<T> sourceType, final Class<D> destinationType) {
		return mapper.mapAsList(dataList, TypeFactory.valueOf(sourceType), TypeFactory.valueOf(destinationType));
	}

	/**
	 * 映射出一个新类型的数据对象列表。
	 *
	 * @param dataList 源数据列表
	 * @param sourceType 源类型
	 * @param destinationType 目标类型
	 * @return 目标类型的数据对象列表
	 */
	public static <T, D> List<D> mapList(Iterable<T> dataList, final Type<T> sourceType, final Type<D> destinationType) {
		return mapper.mapAsList(dataList, sourceType, destinationType);
	}

	/**
	 * 映射出一个新类型的数据对象数组。
	 *
	 * @param sourceArray 源数组
	 * @param destinationArray 目标数组
	 * @param destinationType 目标类型
	 * @return 目标类型的数据对象列表
	 */
	public static <T, D> D[] mapAsArray(final T[] sourceArray, final D[] destinationArray, final Class<D> destinationClass) {
		return mapper.mapAsArray(destinationArray, sourceArray, destinationClass);
	}

	/**
	 * 映射出一个新类型的数据对象数组。
	 *
	 * @param sourceArray 源数组
	 * @param destinationArray 目标数组
	 * @param sourceType 源类型
	 * @param destinationType 目标类型
	 * @return 目标类型的数据对象数组
	 */
	public static <T, D> D[] mapAsArray(T[] sourceArray, D[] destinationArray, Type<T> sourceType, Type<D> destinationType) {
		return mapper.mapAsArray(destinationArray, sourceArray, sourceType, destinationType);
	}

}
